using BepuUtilities.Collections;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;

namespace BepuUtilities.Memory
{
    /// <summary>
    /// 管理标识符值池。从池中抓取ID将挑选之前已经挑选并返回的号码,
    /// 或者,如果这些都不可用,则取大于任何现有ID的最小值。
    /// </summary>
    /// <remarks>This contrasts with the IdPool which operates on unmanaged memory. This version only exists to support use cases where the unmanaged version can't be used-
    /// 例如,在BufferPool中。虽然实现可以共享,但要做到这一点,需要创建足够的支持基础架构,因此拥有仅托管版本会更简单。</MARKEMS>
    public class ManagedIdPool
    {
        private int nextIndex;

        int availableIdCount;
        int[] availableIds;

        /// <summary>
        /// 获取到目前为止声明的任何索引可能具有的最高值。
        /// 这不一定是当前最高的索赔指数;该值可能代表已发布的较早索赔。
        /// -1\f25 Not-1\f6(无人认领)。
        /// </summary>
        public int HighestPossiblyClaimedId
        {
            get { return nextIndex - 1; }
        }

        /// <summary>
        /// 获取池中等待的以前返回的ID数。
        /// </summary>
        public int AvailableIdCount => availableIdCount;

        /// <summary>
        /// 为返回的ID获取ID池的容量。
        /// </summary>        
        /// public int acity=>AvailableIds.Length;


        public ManagedIdPool(int initialCapacity)
        {
            nextIndex = 0;
            availableIdCount = 0;
            Debug.Assert(initialCapacity > 0);
            availableIds = new int[initialCapacity];
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public int Take()
        {
            if (availableIdCount > 0)
                return availableIds[--availableIdCount];
            return nextIndex++;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Return(int id)
        {
            if (availableIdCount == availableIds.Length)
            {
                Debug.Assert(availableIdCount > 0);
                InternalResize(availableIdCount * 2);
            }
            ReturnUnsafely(id);
        }

        /// <summary>
        /// 将id返回到池,而不检查是否需要调整可用id堆栈的大小。
        /// </summary>
        /// <param name="id">要返回的ID。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void ReturnUnsafely(int id)
        {
            Debug.Assert(availableIds.Length > availableIdCount);
            availableIds[availableIdCount++] = id;
        }

        /// <summary>
        /// 重置IdPool。
        /// </summary>
        public void Clear()
        {
            nextIndex = 0;
            availableIdCount = 0;
        }

        void InternalResize(int newSize)
        {
            Debug.Assert(availableIds.Length != newSize, "Did you really mean to resize this? Nothing changed!");
            Array.Resize(ref availableIds, newSize);
        }

        /// <summary>
        /// 确保基础ID队列可以容纳至少一定数量的ID。
        /// </summary>
        /// <param name="count">要在可用ID队列中为其预分配空间的元素数。</param>
        public void EnsureCapacity(int count)
        {
            if (availableIds.Length < count)
                InternalResize(count);
        }

        /// <summary>
        /// 将可用ID队列缩小到可以满足给定计数和当前可用ID计数的最小大小。
        /// </summary>
        /// <param name="minumCount">可用ID队列中保证空间的元素数。</param>
        public void Compact(int minimumCount)
        {
            var targetLength = minimumCount > availableIdCount ? minimumCount : availableIdCount;
            if (availableIds.Length > targetLength)
            {
                InternalResize(targetLength);
            }
        }

        /// <summary>
        /// 将基础缓冲区大小调整为保存给定计数和当前可用id计数所需的最小大小。
        /// </summary>
        /// <param name="count">可用ID队列中保证空间的元素数。</param>
        public void Resize(int count)
        {
            var targetLength = count > availableIdCount ? count : availableIdCount;
            if (availableIds.Length != targetLength)
            {
                InternalResize(targetLength);
            }
        }
    }
}
